TL;DR

获得链表的第 N 个节点。系列目录见 前言和目录

需求

实现一个 getNth() 方法,传入一个链表和一个索引,返回索引代表的节点。索引以 0 为起始,第一个元素索引为 0 ,第二个为 1 ,以此类推。比如:

getNth(1 -> 2 -> 3 -> null, 0).data === 1
getNth(1 -> 2 -> 3 -> null, 1).data === 2

传入的索引必须是在效范围内,即 0..length-1 ,如果索引不合法或者链表为空都需要抛出异常。

递归版本

假设函数定义为 getNth(head, idx) ,递归过程为:当 idx 为零,直接返回该节点,否则递归调用 getNth(head.next, idx - 1) 。再处理下边界情况就完成了,代码如下:

function getNth(head, idx) {
  if (!head || idx < 0) throw 'invalid argument'
  if (idx === 0) return head
  return getNth(head.next, idx - 1)
}

循环版本

我选择的 for 循环,这样方便把边界情况检查都放到循环里去。如果循环结束还没有查到节点,那肯定是链表或者索引不合法,直接抛异常即可。对比这两个版本和 02 Length & Count 的例子,不难看出循环可以比递归更容易地处理边界情况,因为一些条件检查可以写进循环的头部,递归就得自己写 if/else 逻辑。

function getNthV2(head, idx) {
  for (let node = head; node && idx >= 0; node = node.next, idx--) {
    if (idx === 0) return node
  }
  throw 'invalid argument'
}

参考资料

Codewars Kata
GitHub 的代码实现
GitHub 的测试


darkbaby123
1.4k 声望67 粉丝